home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / GnomeCodecInstall / MainWindow.py < prev    next >
Text File  |  2009-10-20  |  16KB  |  437 lines

  1. # -*- coding: utf-8 -*-
  2. # Copyright (c) 2008 Sebastian Dr├╢ge <sebastian.droege@collabora.co.uk>, GPL
  3.  
  4. import gettext
  5. from gettext import gettext as _
  6. import gobject
  7. import gtk
  8. import pango
  9. import gst
  10. import gst.pbutils
  11. import apt
  12. import PackageWorker
  13.  
  14. # the list columns
  15. (LIST_PKG_TO_INSTALL,
  16.  LIST_PKG_NAME,
  17.  LIST_PKG_REQUEST) = range(3)
  18.  
  19. # codecs that might be problematic for patent reasons
  20. CODEC_WARNING_LIST = [ "gstreamer0.10-plugins-bad",
  21.                        "gstreamer0.10-plugins-bad-multiverse",
  22.                        "gstreamer0.10-ffmpeg",
  23.                        "gstreamer0.10-plugins-ugly",
  24.                      ]
  25.  
  26. class CodecDetailsView(gtk.TextView):
  27.   " special view to display for the codec information "
  28.   def __init__(self):
  29.     gtk.TextView.__init__(self)
  30.     self.set_property("editable", False)
  31.     self.set_cursor_visible(False)
  32.     self.set_wrap_mode(gtk.WRAP_WORD)
  33.     self.buffer = gtk.TextBuffer()
  34.     self.set_buffer(self.buffer)
  35.     # tag names for the elements we insert
  36.     self.buffer.create_tag("summary", 
  37.                            scale=pango.SCALE_LARGE,
  38.                            weight=pango.WEIGHT_BOLD)
  39.     self.buffer.create_tag("homepage", 
  40.                            weight=pango.WEIGHT_BOLD)
  41.     self.buffer.create_tag("provides", 
  42.                            weight=pango.WEIGHT_BOLD)
  43.     self.buffer.create_tag("description", 
  44.                            weight=pango.WEIGHT_BOLD)
  45.     self.buffer.insert_with_tags_by_name(self.buffer.get_start_iter(),
  46.                                          _("No package selected"),
  47.                                          "summary")
  48.  
  49.   def show_codec(self, pkg=None, requests=None):
  50.     # clear the buffer
  51.     self.buffer.set_text("")
  52.     iter = self.buffer.get_start_iter()
  53.     self.buffer.place_cursor(iter)
  54.     # if nothing is selected we are done
  55.     if pkg is None:
  56.       self.buffer.insert_with_tags_by_name(iter,
  57.                                            _("No package selected"),
  58.                                            "summary")
  59.       return 
  60.     # now format the description
  61.     self.buffer.insert_with_tags_by_name(iter, 
  62.                                          pkg.summary,
  63.                                          "summary")
  64.     self.buffer.insert(iter, "\n\n")
  65.     if pkg.homepage:
  66.       self.buffer.insert_with_tags_by_name(iter, 
  67.                                            _("Homepage:")+"\n", 
  68.                                            "homepage")
  69.       self.buffer.insert(iter, pkg.homepage + "\n\n")
  70.     self.buffer.insert_with_tags_by_name(iter, 
  71.                                          _("Provides:")+"\n", 
  72.                                          "provides")
  73.     for request in requests:
  74.       self.buffer.insert(iter, request.description + "\n")
  75.     self.buffer.insert(iter, "\n")
  76.     self.buffer.insert_with_tags_by_name(iter, 
  77.                                          _("Long Description:")+"\n", 
  78.                                          "description")
  79.     self.buffer.insert(iter, pkg.description + "\n")
  80.  
  81. def set_transient_for_xid(widget, xid):
  82.   try:
  83.     if xid != None:
  84.       parent = gtk.gdk.window_foreign_new(xid)
  85.       if parent != None:
  86.         widget.realize()
  87.         widget.get_window().set_transient_for(parent)
  88.   except:
  89.     pass
  90.  
  91. class MainWindow(object):
  92.  
  93.   def __init__(self,requests,xid):
  94.     self._requests = requests
  95.     self._window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  96.     self._window.set_title(_("Install Multimedia Plugins"))
  97.     self._window.set_property("default_width", 600)
  98.     self._window.set_property("default_height", 500)
  99.     self._window.set_border_width(10)
  100.     self._window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
  101.  
  102.     self._return_code = gst.pbutils.INSTALL_PLUGINS_NOT_FOUND
  103.  
  104.     self._window.connect("delete_event", self._delete_event)
  105.     self._window.connect("destroy", self._destroy)
  106.     set_transient_for_xid(self._window, xid)
  107.  
  108.     vbox_window = gtk.VBox()
  109.     vbox_packages = gtk.VBox(homogeneous=False)
  110.  
  111.     label = gtk.Label()
  112.     label.set_line_wrap(True)
  113.     label.set_justify(gtk.JUSTIFY_LEFT)
  114.     label.set_alignment(0.0, 0.0)
  115.  
  116.     plugins = ""
  117.     for request in self._requests:
  118.       plugins += "\n- " + request.description
  119.     label.set_markup(_("<b><big>Please select the packages for installation "
  120.                        "to provide the following plugins:</big></b>\n") + plugins)
  121.     vbox_packages.pack_start(label, False, False, 10)
  122.  
  123.     self._package_list_model = gtk.ListStore(gobject.TYPE_BOOLEAN, 
  124.                                              gobject.TYPE_STRING, 
  125.                                              gobject.TYPE_PYOBJECT)
  126.  
  127.     self._package_list = gtk.TreeView(self._package_list_model)
  128.     self._package_list.set_headers_visible(True)
  129.     self._package_list.connect("cursor-changed", self._package_cursor_changed)
  130.     
  131.     toggle_renderer = gtk.CellRendererToggle()
  132.     toggle_renderer.connect("toggled", self._toggle_install)
  133.     self._package_list.append_column(gtk.TreeViewColumn(None, toggle_renderer, active=0))
  134.     text_renderer = gtk.CellRendererText()
  135.     text_renderer.set_data("column", 1)
  136.     self._package_list.append_column(gtk.TreeViewColumn(_("Package"), text_renderer, text=1))
  137.  
  138.     scrolled_window = gtk.ScrolledWindow()
  139.     scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
  140.     #scrolled_window.set_shadow_type(gtk.SHADOW_IN)
  141.     scrolled_window.add(self._package_list)
  142.  
  143.     vbox_packages.pack_start(scrolled_window, True, True, 10)
  144.  
  145.     expander = gtk.Expander(_("Details") + ":")
  146.     expander.connect("notify::expanded", self._package_details_expanded)
  147.  
  148.     self._package_details = CodecDetailsView()
  149.     scrolled_window = gtk.ScrolledWindow()
  150.     scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
  151.     #scrolled_window.set_shadow_type(gtk.SHADOW_IN)
  152.     scrolled_window.add_with_viewport(self._package_details)
  153.  
  154.     expander.add(scrolled_window)
  155.     vbox_packages.pack_start(expander, False, False, 10)
  156.     
  157.     vbox_window.pack_start(vbox_packages, True, True, 0)
  158.  
  159.     button_box = gtk.HButtonBox()
  160.     button_box.set_layout(gtk.BUTTONBOX_END)
  161.     button_box.set_spacing(5)
  162.  
  163.     #TODO integrate help by calling yelp
  164.     #btn = gtk.Button(_("Help"), gtk.STOCK_HELP)
  165.     #button_box.add(btn)
  166.     #button_box.set_child_secondary(btn, True)
  167.  
  168.     btn = gtk.Button(_("Cancel"), gtk.STOCK_CANCEL)
  169.     btn.connect("clicked", self._canceled)
  170.     button_box.add(btn)
  171.  
  172.     btn = gtk.Button(_("Install"), None)
  173.     btn.connect("clicked", self._install_selection)
  174.     button_box.add(btn)
  175.  
  176.     vbox_window.pack_start(button_box, False, False, 0)    
  177.     self._window.add(vbox_window)
  178.  
  179.     self._window.show_all()
  180.  
  181.  
  182.   def modal_dialog(self, type, primary, secondary=""):
  183.     " helper that shows a modal dialog of the given type "
  184.     dlg = gtk.MessageDialog(self._window, 
  185.                             gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, 
  186.                             type,
  187.                             gtk.BUTTONS_OK, 
  188.                             primary)
  189.     dlg.set_title(primary)
  190.     dlg.format_secondary_text(secondary)
  191.     res = dlg.run()
  192.     dlg.destroy()
  193.     return res
  194.  
  195.   def _package_cursor_changed(self, treeview, data=None):
  196.     selection = treeview.get_selection()
  197.     (model, iter) = selection.get_selected()
  198.     if iter:
  199.       pkgname = model.get_value(iter, LIST_PKG_NAME)
  200.       requests = model.get_value(iter, LIST_PKG_REQUEST)
  201.       self._package_details.show_codec(self.cache[pkgname], requests)
  202.     else:
  203.       self._package_details.show_codec(None)
  204.  
  205.   def _package_details_expanded(self, expander, param_spec, data=None):
  206.     if expander.get_expanded():
  207.       expander.get_child().show_all()
  208.       expander.set_size_request(-1, 120)
  209.     else:
  210.       expander.set_size_request(-1, -1)
  211.       expander.get_child().hide_all()
  212.  
  213.   def _confirm_codec_install(self, install_list):
  214.     " helper that shows a codec warning dialog "
  215.     for pkgname in CODEC_WARNING_LIST:
  216.       if pkgname in install_list:
  217.         break
  218.     else:
  219.       return
  220.     dia = gtk.MessageDialog(parent=self._window,
  221.                             type=gtk.MESSAGE_WARNING,
  222.                             buttons=gtk.BUTTONS_CANCEL)
  223.     header = _("Confirm installation of restricted software")
  224.     body = _("The use of this software may be "
  225.              "restricted in some countries. You "
  226.              "must verify that one of the following is true:\n\n"
  227.              "* These restrictions do not apply in your country "
  228.              "of legal residence\n"
  229.              "* You have permission to use this software (for "
  230.              "example, a patent license)\n"
  231.              "* You are using this software for research "
  232.              "purposes only")
  233.     dia.set_markup("<big><b>%s</b></big>\n\n%s" % (header,body))
  234.     dia.add_button(_("C_onfirm"), gtk.RESPONSE_OK)
  235.     res = dia.run()
  236.     dia.hide()
  237.     if res != gtk.RESPONSE_OK:
  238.       return False
  239.     return True
  240.  
  241.   def _toggle_install(self, cell, path, data=None):
  242.     iter = self._package_list_model.get_iter((int(path),))
  243.     name = self._package_list_model.get_value(iter, LIST_PKG_NAME)
  244.     enabled = self._package_list_model.get_value(iter, LIST_PKG_TO_INSTALL)
  245.     enabled = not enabled
  246.     self._package_list_model.set(iter, LIST_PKG_TO_INSTALL, enabled)
  247.  
  248.   def _populate_list(self):
  249.     dlg = gtk.Dialog(_("Searching Plugin Packages"), self._window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, None)
  250.     dlg.set_has_separator(False)
  251.     dlg.set_deletable(False)
  252.     dlg.set_border_width(5)
  253.  
  254.     label = gtk.Label()
  255.     label.set_markup("<b><big>" + _("Searching Plugin Packages") + "</big></b>\n" + 
  256.                      _("This might take up to one or two minutes."))
  257.  
  258.     dlg.vbox.pack_start(label, True, True, 5)
  259.  
  260.     progressbar = gtk.ProgressBar()
  261.     progressbar.set_fraction(0.0)
  262.     dlg.vbox.pack_start(progressbar, True, True, 5)
  263.  
  264.     dlg.show_all()
  265.  
  266.     self.update_ui()
  267.  
  268.     progressbar.set_text(_("Loading package cache..."))
  269.     self.cache = apt.Cache(PackageWorker.GtkOpProgress())
  270.     
  271.     self.update_ui()
  272.     
  273.     npackages = 0
  274.  
  275.     package_count = len(self.cache)
  276.     
  277.     progressbar.set_text(_("Searching for requested plugins..."))
  278.  
  279.     # maps request to pkgrecord entry and provide information if
  280.     # gst caps must be used or the string needs to be split 
  281.     requests_map = [
  282.       #  request    pkgrecord             caps  split
  283.       ("decoder", "Gstreamer-Decoders", True, False),
  284.       ("encoder", "Gstreamer-Encoders", True, False),
  285.       ("urisource", "Gstreamer-Uri-Sources", False, True),
  286.       ("urisink", "Gstreamer-Uri-Sinks", False, True),
  287.       ("element", "Gstreamer-Elements", False, True),
  288.     ]
  289.  
  290.     # iterate all the packages
  291.     for (cur_package, pkg) in enumerate(self.cache):
  292.  
  293.       if cur_package % 500 == 0:
  294.         progressbar.set_fraction(float(cur_package) / package_count)
  295.  
  296.       self.update_ui()
  297.       if pkg.isInstalled and not pkg.isUpgradable:
  298.         continue
  299.  
  300.       record = pkg.candidateRecord
  301.       if not record:
  302.         continue
  303.       if not record.has_key("Gstreamer-Version"):
  304.         continue
  305.       major, minor = pkg.candidateRecord["Gstreamer-Version"].split(".")
  306.  
  307.       if (int(major) != self._requests[0].major or 
  308.           int(minor) != self._requests[0].minor):
  309.         continue
  310.  
  311.       add_pkg = False
  312.       pkg_requests = []
  313.  
  314.       # check requests
  315.       for request in self._requests:
  316.         self.update_ui()
  317.  
  318.         for (request_str, pkgrecord_str, check_caps, do_split) in requests_map:
  319.           if request.gstkind == request_str:
  320.             if not record.has_key(pkgrecord_str):
  321.               continue
  322.             if check_caps:
  323.               caps = gst.Caps(record[pkgrecord_str])
  324.               if request.caps.intersect(caps):
  325.                 add_pkg = True
  326.                 pkg_requests.append(request)
  327.                 break
  328.             if do_split:
  329.               elms = record[pkgrecord_str].split(",")
  330.               if request.feature in elms:
  331.                 add_pkg = True
  332.                 pkg_requests.append(request)
  333.                 break
  334.  
  335.       if add_pkg:
  336.         npackages += 1
  337.         iter = self._package_list_model.append()
  338.         self._package_list_model.set(iter,
  339.                                      LIST_PKG_TO_INSTALL, True,
  340.                                      LIST_PKG_NAME, pkg.name,
  341.                                      LIST_PKG_REQUEST, pkg_requests)
  342.     
  343.     self._package_list_model.set_sort_column_id(LIST_PKG_NAME, gtk.SORT_ASCENDING)
  344.     self.update_ui()
  345.  
  346.     dlg.destroy()
  347.     return npackages
  348.  
  349. #  def _on_button_help_clicked(self, widget):
  350. #      if os.path.exists("/usr/bin/yelp"):
  351. #          subprocess.Popen(["/usr/bin/yelp", "ghelp:gnome-codec-install"])
  352. #      else:
  353. #          d = gtk.MessageDialog(parent=self.window_main,
  354. #                                flags=gtk.DIALOG_MODAL,
  355. #                                type=gtk.MESSAGE_ERROR,
  356. #                                buttons=gtk.BUTTONS_CLOSE)
  357. #          header = _("No help available")
  358. #          msg = _("To display the help, you need to install the "
  359. #                  "\"yelp\" application.")
  360. #          d.set_title("")
  361. #          d.set_markup("<big><b>%s</b></big>\n\n%s" % (header, msg))
  362. #          d.run()
  363. #          d.destroy()
  364.  
  365.   def _delete_event(self, widget, event, data=None):
  366.     return False
  367.  
  368.   def _destroy(self, widget, data=None):
  369.     gtk.main_quit()
  370.  
  371.   def _canceled(self, widget, data=None):
  372.     self._return_code = gst.pbutils.INSTALL_PLUGINS_USER_ABORT
  373.     gtk.main_quit()
  374.  
  375.   def update_ui(self):
  376.     " helper that processes all pending events "
  377.     while gtk.events_pending():
  378.       gtk.main_iteration()
  379.  
  380.   def _install_selection(self, widget, data=None):
  381.     iter = self._package_list_model.get_iter_first()
  382.     packages = []
  383.  
  384.     while iter:
  385.       if self._package_list_model.get_value(iter, LIST_PKG_TO_INSTALL):
  386.         packages.append((self._package_list_model.get_value(iter, LIST_PKG_NAME), 
  387.                          self._package_list_model.get_value(iter, LIST_PKG_REQUEST)))
  388.       iter = self._package_list_model.iter_next(iter)
  389.  
  390.     if not packages or len(packages) == 0:
  391.       self.modal_dialog(gtk.MESSAGE_WARNING,
  392.                         _("No packages selected"))
  393.       self._return_code = gst.pbutils.INSTALL_PLUGINS_NOT_FOUND
  394.       return
  395.  
  396.     # check codec install message
  397.     if not self._confirm_codec_install(set([package[LIST_PKG_TO_INSTALL] for package in packages])):
  398.       return
  399.  
  400.     worker = PackageWorker.PackageWorker()
  401.     install_success = worker.perform_action(self._window, set([package[LIST_PKG_TO_INSTALL] for package in packages]), set())
  402.  
  403.     if install_success:
  404.       if not self._requests or len(self._requests) == 0:
  405.         self.modal_dialog(gtk.MESSAGE_INFO,
  406.                           _("Packages successfully installed"),
  407.                           _("The selected packages were successfully "
  408.                             "installed and provided all requested plugins"))
  409.         self._return_code = gst.pbutils.INSTALL_PLUGINS_SUCCESS
  410.       else:
  411.         self.modal_dialog(gtk.MESSAGE_INFO,
  412.                           _("Packages successfully installed"),
  413.                           _("The selected packages were successfully "
  414.                             "installed but did not provide all requested "
  415.                             "plugins"))
  416.         self._return_code = gst.pbutils.INSTALL_PLUGINS_PARTIAL_SUCCESS
  417.     else:
  418.       self.modal_dialog(gtk.MESSAGE_ERROR,
  419.                         _("No packages installed"),
  420.                         _("None of the selected packages were installed."))
  421.       self._return_code = gst.pbutils.INSTALL_PLUGINS_ERROR
  422.     gtk.main_quit()
  423.  
  424.   def main(self):
  425.     npackages = self._populate_list()
  426.     if npackages == 0:
  427.       plugins = ""
  428.       for request in self._requests:
  429.         plugins += "\n" + request.description
  430.       self.modal_dialog(gtk.MESSAGE_WARNING,
  431.                         _("No packages with the requested plugins found"),
  432.                         _("The requested plugins are:\n") + plugins)
  433.       return gst.pbutils.INSTALL_PLUGINS_NOT_FOUND
  434.     gtk.main()
  435.     return self._return_code
  436.  
  437.